package com.mrogrape.notepad.ui;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.Box;
import javax.swing.JLabel;
import javax.swing.JToolBar;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

import com.mrogrape.notepad.data.ViewContext;
import com.mrogrape.notepad.ui.editor.TextEditor;
import com.mrogrape.util.StringUtils;


public class StatusBar extends JToolBar implements ChangeListener,DocumentListener,CaretListener,PropertyChangeListener{

	/** serialVersionUID */
	private static final long serialVersionUID = 7252083844408778627L;

	public StatusBar() {
		this.initComponents();
	}

	private void initComponents() {

		this.setFloatable(false);

		this.infoLable = SwingComponentFactory.createTextLabel("No informations");
		this.add(this.infoLable);

		Component horizontalGlue = Box.createHorizontalGlue();
		this.add(horizontalGlue);

		this.wordLabel = SwingComponentFactory.createTextLabel("0 character(s)");
		this.add(this.wordLabel);

		this.wordSeparator = SwingComponentFactory.createTextLabel(" | ");
		this.add(this.wordSeparator);

		this.locationLabel = SwingComponentFactory.createTextLabel("row 0, col 0");
		this.add(this.locationLabel);

		this.locationSeparator = SwingComponentFactory.createTextLabel(" | ");
		this.add(this.locationSeparator);

		this.encodingLabel = SwingComponentFactory.createTextLabel("");
		this.add(this.encodingLabel);

		this.encodingSeparator = SwingComponentFactory.createTextLabel(" | ");
		this.add(this.encodingSeparator);

		this.editableLabel = SwingComponentFactory.createTextLabel("");
		this.add(this.editableLabel);

		this.editableSeparator = SwingComponentFactory.createTextLabel(" | ");
		this.add(this.editableSeparator);

		this.heapMonitor = new MemoryMonitor();
		this.heapMonitor.startMonitoring();
		this.heapMonitor.setMaximumSize(new Dimension(150, 14));
		this.add(this.heapMonitor);
	}

	@Override
	public void changedUpdate(DocumentEvent e) {

		this.textChanged(e);
	}

	@Override
	public void insertUpdate(DocumentEvent e) {

		this.textChanged(e);
	}

	@Override
	public void removeUpdate(DocumentEvent e) {
		this.textChanged(e);
	}

	@Override
	public void stateChanged(ChangeEvent e) {

		this.currentTextEditorChanged(e);
	}

	@Override
	public void caretUpdate(CaretEvent e) {

		if(this.currentEditor != null){

			this.setCaretLocation(this.currentEditor.getCaretLineNumber(), this.currentEditor.getCaretOffsetFromLineStart());
		}
	}

	@Override
	public void propertyChange(PropertyChangeEvent evt) {

		if(this.currentEditor != null){

			if(TextEditor.PROPERTY_CHARSET.equals(evt.getPropertyName())){

				this.setEncoding(String.valueOf(evt.getNewValue()));
			}
			else if(TextEditor.PROPERTY_EDITABLE.equals(evt.getPropertyName())){

				this.setEditable(Boolean.valueOf(evt.getNewValue().toString()));
			}
		}
	}

	@Override
	public void setVisible(boolean isVisible){
		super.setVisible(isVisible);
		if(isVisible){
			this.heapMonitor.startMonitoring();
		}else{
			this.heapMonitor.stopMonitoring();
		}
	}

	/**
	 * 设置要在状态栏上显示的消息。
	 * 
	 * @param info
	 */
	public void setInformation(final String info){

		EventQueue.invokeLater(new Runnable(){

			@Override
			public void run() {

				if(StringUtils.isEmpty(info)){
					StatusBar.this.infoLable.setText("(No informations)");
				}
				else{
					StatusBar.this.infoLable.setText(info);
				}
			}});
	}

	private void setWordCount(int count){

		String text = count + " char";

		this.wordLabel.setText(text);
	}

	private void setCaretLocation(int row, int col){

		String text = "row:"+ (row+1) + ",col:" + (col+1);
		this.locationLabel.setText(text);
	}

	private void setEncoding(String encoding){

		this.encodingLabel.setText(encoding);
	}

	private void setEditable(boolean editable){

		if(editable){
			this.editableLabel.setText("Writable");

		}
		else{
			this.editableLabel.setText("Readonly");
		}

	}

	public void setHeapMonitorVisible(boolean visible){

		this.heapMonitor.setVisible(visible);
		this.editableSeparator.setVisible(visible);
		if(visible){
			this.heapMonitor.startMonitoring();
		}else{
			this.heapMonitor.stopMonitoring();
		}
	}

	private void setTextEditorMonitorVisible(boolean visible){

		this.wordLabel.setVisible(visible);
		this.wordSeparator.setVisible(visible);
		this.locationLabel.setVisible(visible);
		this.locationSeparator.setVisible(visible);
		this.encodingLabel.setVisible(visible);
		this.encodingSeparator.setVisible(visible);
		this.editableLabel.setVisible(visible);
		this.editableSeparator.setVisible(visible);
	}

	private void textChanged(DocumentEvent e){

		if(this.currentEditor != null){

			// 字数
			this.setWordCount(this.currentEditor.getText().length());
		}
	}

	private void currentTextEditorChanged(ChangeEvent e){

		if(this.currentEditor != null){
			this.currentEditor.removeDocumentListener(this);
			this.currentEditor.removePropertyChangeListener(this);
			this.currentEditor.removeCaretListener(this);
		}

		this.currentEditor = ViewContext.getCurrentTextEditor();

		if(this.currentEditor != null){
			this.currentEditor.addDoucumentListener(this);
			this.currentEditor.addPropertyChangeListener(this);
			this.currentEditor.addCaretListener(this);

			this.setTextEditorMonitorVisible(true);
			this.setWordCount(this.currentEditor.getText().length());
			this.setCaretLocation(this.currentEditor.getCaretLineNumber(), this.currentEditor.getCaretOffsetFromLineStart());
			this.setEncoding(this.currentEditor.getCharset());
			this.setEditable(this.currentEditor.isEditable());

		}
		else{
			this.setTextEditorMonitorVisible(false);
		}
	}

	private TextEditor currentEditor;

	private JLabel infoLable;
	private JLabel wordLabel;
	private JLabel wordSeparator;
	private JLabel locationLabel;
	private JLabel locationSeparator;
	private JLabel encodingLabel;
	private JLabel encodingSeparator;
	private JLabel editableLabel;
	private JLabel editableSeparator;
	private MemoryMonitor heapMonitor;
}
